#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <optional>
#include <algorithm>

using namespace std;

class Solution {
public:
    string validIPAddress(string queryIP) {
        string type = "Neither";

        /* 字符串分割 */
        optional<vector<string>> splitString = GetSplitString(queryIP, '.');
        if (splitString.has_value()) {
            if (isIpv4Data(splitString.value())) {
                type = "IPv4";
            }
        } else {
            splitString = GetSplitString(queryIP, ':');
            if (!splitString.has_value()) {
                return type;
            }

            if (isIpv6Data(splitString.value())) {
                type = "IPv6";
            } 
        }           
        
        return type;
    }

    optional<vector<string>> GetSplitString(const string& queryIP, char splitCh)
    {
        vector<string> vec{};
        string newQueryIp = queryIP + splitCh;

        while (!newQueryIp.empty()) {
            auto pos = newQueryIp.find(splitCh);
            string tmp = newQueryIp.substr(0, pos);
            vec.emplace_back(tmp);
            newQueryIp = newQueryIp.substr(pos + 1);
        }

        if (vec.size() > 1) {
            return vec;
        }

        return std::nullopt;
    }

    bool isIpv4Data(const vector<string>& dataVec)
    {
        if (dataVec.size() != 4) {
            return false;
        }

        for (const auto& data : dataVec) {
            if (data.length()==0 || data.length() > 3) {
                return false;
            }

            /* 前导0判断 */
            if (data.length() != 1 && data[0] == '0') {
                return false;
            }

            for (auto ch : data) {
                if (!isdigit(ch)) {
                    return false;
                }
            }

            int num = stoi(data);
            if (num > 0xff) {
                return false;
            }
        }

        return true;
    }

    bool isIpv6Data(const vector<string>& dataVec)
    {
        if (dataVec.size() != 8) {
            return false;
        }

        for (const auto& data : dataVec) {
            if (data.length() == 0 || data.length() > 4) {
                return false;
            }

            for (auto ch : data) {
                if (!isxdigit(ch)) {
                    return false;
                }
            }
        }

        return true;
    }   
};

int main() 
{
    Solution s;
    string str = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";

    cout << s.validIPAddress(str) << endl;

    return 0;
}